/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.springBoot.springBootSysCore.common.persistence;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.*;
import javax.persistence.Entity;
import javax.swing.text.html.parser.*;
import javax.xml.bind.annotation.XmlTransient;

import com.alibaba.fastjson.annotation.JSONField;
import com.google.gson.annotations.Expose;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.hibernate.annotations.GenericGenerator;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Maps;
import com.springBoot.springBootSysCore.common.comment.annotation.MyComment;
import com.springBoot.springBootSysCore.common.config.Global;
import com.springBoot.springBootSysCore.modules.entity.system.SysUser;
import com.springBoot.springBootSysCore.modules.entity.utils.UserUtils;
import org.hibernate.annotations.Type;
import org.omg.CORBA.Object;


/**
 * Entity支持类
 *
 * //@MappedSuperclass 用在父类上面。当这个类肯定是父类时，加此标注。如果改成@Entity，则继承后，多个类继承，只会生成一个表，而不是多个继承，生成多个表
 * @author ThinkGem
 * @version 2014-05-16
 */
@MappedSuperclass
public abstract class BaseEntity<T> extends PageEntity<T> implements Serializable {
	private static final long serialVersionUID = 1L;
	@Expose
	protected String id;//实体编号（唯一标识）
	@JsonIgnore
	@XmlTransient
	@Transient
	@JSONField(serialize=false)
	protected SysUser currentUser;//当前用户

	protected Map<String, String> sqlMap;// 自定义SQL（SQL标识，SQL内容）
	//是否是新记录（默认：false），调用setIsNewRecord()设置新记录，使用自定义ID。
	// 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
	protected boolean isNewRecord = false;

	public BaseEntity() {
		
	}
	
	public BaseEntity(String id) {
		this();
		this.id = id;
	}
//	@Id
//    @Column(name = "id")
//    @GeneratedValue(strategy = GenerationType.IDENTITY)
	@Id
    @Column(name = "ID",length=50,nullable=false)
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
	@MyComment("主键: ID")
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
	
	@JsonIgnore
	@XmlTransient
	@Transient
	public SysUser getCurrentUser() {
		if(currentUser == null){
			currentUser = UserUtils.getUser();
		}
		return currentUser;
	}
	
	public void setCurrentUser(SysUser currentUser) {
		this.currentUser = currentUser;
	}
	@JsonIgnore
	@XmlTransient
	@Transient
	public Map<String, String> getSqlMap() {
		if (sqlMap == null){
			sqlMap = Maps.newHashMap();
		}
		return sqlMap;
	}

	public void setSqlMap(Map<String, String> sqlMap) {
		this.sqlMap = sqlMap;
	}
	
	/**
	 * 插入之前执行方法，子类实现
	 */
	public abstract void preInsert();
	
	/**
	 * 更新之前执行方法，子类实现
	 */
	public abstract void preUpdate();
	
    /**
	 * 是否是新记录（默认：false），调用setIsNewRecord()设置新记录，使用自定义ID。
	 * 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
     * @return
     */
	@Transient
	public boolean getIsNewRecord() {
        return isNewRecord || StringUtils.isBlank(getId());
    }

	/**
	 * 是否是新记录（默认：false），调用setIsNewRecord()设置新记录，使用自定义ID。
	 * 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
	 */
	public void setIsNewRecord(boolean isNewRecord) {
		this.isNewRecord = isNewRecord;
	}

	/**
	 * 全局变量对象
	 */
	@JsonIgnore
	@Transient
	public Global getGlobal() {
		return Global.getInstance();
	}
	
	/**
	 * 获取数据库名称
	 */
	@JsonIgnore
	@Transient
	public String getDbName(){
		return Global.getConfig("jdbc.type");
	}
	
    public boolean equals(Object obj) {
        if (null == obj) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (!getClass().equals(obj.getClass())) {
            return false;
        }
        BaseEntity<?> that = (BaseEntity<?>) obj;
        return null == this.getId() ? false : this.getId().equals(that.getId());
    }
    
    @Override
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
    
	/**
	 * 删除标记（0：正常；1：删除；2：审核；）
	 */
//	public static final String delFlagNormal = "0";
//	public static final String delFlagDelete = "1";
//	public static final String delFlagAudit = "2";

	/**
	 * 自动设置值 只包括基础类型
	 * @param entityDb 数据库实体
	 * @param entity
	 */
//	public  void EntityCopy(T entityDb, T entity){
	public  void EntityCopy(T entityDb, java.lang.Object entity){
		Field[] field = entity.getClass().getDeclaredFields(); // 获取实体类的所有属性，返回Field数组
		try {
			for (int j = 0; j < field.length; j++) { // 遍历所有属性
				String name = field[j].getName(); // 获取属性的名字
				name = name.substring(0, 1).toUpperCase() + name.substring(1); // 将属性的首字符大写，方便构造get，set方法
				String type = field[j].getGenericType().toString(); // 获取属性的类型
				if (type.equals("class java.lang.String")){ // 如果type是类类型，则前面包含"class "，后面跟类名
					Method m = entity.getClass().getMethod("get" + name);
					String value = (String) m.invoke(entity); // 调用getter方法获取属性值
					if(StringUtils.isNotBlank(value)){
						m = entityDb.getClass().getMethod("set"+name,String.class);
						m.invoke(entityDb, value);
					}
				}
				if (type.equals("class java.lang.Integer")) {
					Method m = entity.getClass().getMethod("get" + name);
					Integer value = (Integer) m.invoke(entity);
					if(value!=null){
						m = entityDb.getClass().getMethod("set"+name,Integer.class);
						m.invoke(entityDb, value);
					}
				}
				if (type.equals("int")) {
					Method m = entity.getClass().getMethod("get" + name);
					Integer value = (Integer) m.invoke(entity);
					if(value!=null){
						m = entityDb.getClass().getMethod("set"+name,int.class);
						m.invoke(entityDb, value);
					}
				}
				if (type.equals("class java.lang.Boolean")) {
					Method m = entity.getClass().getMethod("get" + name);
					Boolean value = (Boolean) m.invoke(entity);
					if(value!=null){
						m = entityDb.getClass().getMethod("set"+name,Boolean.class);
						m.invoke(entityDb, value);
					}
				}
				if (type.equals("boolean")) {
					Method m = entity.getClass().getMethod("is" + name);
					Boolean value = (Boolean) m.invoke(entity);
					if(value!=null){
						m = entityDb.getClass().getMethod("set"+name,boolean.class);
						m.invoke(entityDb, value);
					}
				}
				if (type.equals("class java.util.Date")) {
					Method m = entity.getClass().getMethod("get" + name);
					Date value = (Date) m.invoke(entity);
					if(value!=null){
						m = entityDb.getClass().getMethod("set"+name,Date.class);
						m.invoke(entityDb,value);
					}
				}
				if(type.equals("class java.math.BigDecimal")){
					Method m = entity.getClass().getMethod("get" + name);
					BigDecimal value = (BigDecimal) m.invoke(entity);
					if(value!=null){
						m = entityDb.getClass().getMethod("set"+name,BigDecimal.class);
						m.invoke(entityDb,value);
					}
				}
				// 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断
			}
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
}
